r"""岭回归（Ridge
Regression）是一种用于处理共线性数据的线性回归改进方法。
和上一篇用基于最小二乘法的线性回归相比，它通过放弃最小二乘的无偏性，
以损失部分信息、降低精度为代价来获得更实际和可靠性更强的回归系数。

1.
概述
岭回归的模型对于存在大量相关特征（这些特征之间存在很高的相关性）的数据时效果远好于基于最小二乘法的线性模型。

原因就是它通过给系数的大小增加一个约束条件（即L2正则化项），来防止模型过度拟合训练数据。
损失函数一般定义为：
L(w)=(y−wX)2+λ∥w∥2
其中λ∥w∥2=λ∑ni=1w2i，也就是L2正则化项。模型训练的过程就是寻找让损失函数L(w)最小的参数w。也就等价于：argmin(y−wX)2  s.t.∑w2ij<s(1)(2)
这两个公式表示，在满足约束条件∑w2ij<s的情况下，计算(y−wX)2的最小值。
2.
创建样本数据
岭回归适用于特征之间有很高关联性的数据集。
所以用scikit - learn中的加州住房数据集，这个数据集有8个房屋售价相关的属性，属性之间关联性高。
数据集的文件获取可以参考：TODO

从上面的文章中下载数据集（是一个zip压缩文件），
如下例所示，下载之后在
D:\share\data中解压，就可以加载了。"""

import os

from sklearn import metrics
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.linear_model import Ridge

data = fetch_california_housing()
X = data["data"]
y = data["target"]
"""大约有2万多条数据。

3.
模型训练
数据加载之后，首先划分训练集和测试集。"""


# 分割训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1)
"""然后用岭回归模型训练数据：
"""

# 初始化岭回归线性模型
reg = Ridge()
# 训练模型
reg.fit(X_train, y_train)
"""这里，用的Ridge()
模型的默认参数，它的一些主要参数如下（训练模型时可根据情况调整参数）：

alpha：控制正则化强度的常量，也就是上面公式中的
λ
，默认值1，设置为0时，就是最小二乘法
fit_intercept：是否拟合此模型的截距，默认
True
copy_X：是否复制X（也就是训练数据），默认
True，设置为False的话，有可能会改变训练数据
tol：算法迭代时，收敛的精度上限
solver：迭代时使用的求解器，包含 ** {auto, svd, cholesky, lsqr, sparse_cg, sag, saga, lbfgs} ** 等算法，默认
auto（根据数据类型自动选择求解器）
最后，用测试数据来验证训练后模型的性能。"""

y_pred = reg.predict(X_test)
mse = metrics.mean_squared_error(y_test, y_pred)
r2 = metrics.r2_score(y_test, y_pred)
m_error = metrics.median_absolute_error(y_test, y_pred)

print("均方误差：{}".format(mse))
print("复相关系数：{}".format(r2))
print("中位数绝对误差：{}".format(m_error))

"""# 运行结果
均方误差：0.0029948538129997903
复相关系数：0.9987534427417275
中位数绝对误差：0.049467455621301726
从结果来看，模型的性能还不错，均方误差和中位数绝对误差都比较小，而复相关系数高，说明在测试数据中，预测的值和实际的值比较接近。

4.
总结
总之，岭回归在很多场景下都有应用，例如多元线性回归、时间序列预测、特征选择等。
它的主要优点是可以处理共线性数据，并且在加入噪声的情况下会有更稳定的性能。

然而，由于其对数据的缩放敏感，岭回归的一个主要局限性是它可能对数据的尺度非常敏感。
此外，岭回归正则化参数的选择通常需要一些经验或者实验来确定，这也增加了其应用的复杂性。

PS.
共线性是指特征之间存在高度相关性，这可能导致线性回归模型的不稳定。"""